package com.ai.modbus;

import com.ai.common.CommonResponse;
import com.ai.entity.made.ModbusNodeInfo;
import com.ai.entity.made.ModbusServerInfo;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

import static com.ai.common.constant.RedisConstants.DEVICE_SIGNAL;
import static com.ai.common.constant.RedisConstants.MODBUS_NODE_IDENTIFIER;
import static net.sf.jsqlparser.parser.feature.Feature.offset;

/**
 * 异步读取modbus节点值
 * @Author jiaok
 * @Date 2024-11-27 13:44
 */
@Slf4j
public class ModbusReadRunnable implements Runnable {
    /**
     * modbus服务器信息
     */
    private ModbusServerInfo modbusServerInfo;
    /**
     * modbus节点列表信息
     */
    private List<ModbusNodeInfo> modbusNodeInfoList;

    private StringRedisTemplate stringRedisTemplate;

    private  Integer threshold ;

    public ModbusReadRunnable(ModbusServerInfo modbusServerInfo, List<ModbusNodeInfo> modbusNodeInfoList,StringRedisTemplate stringRedisTemplate, Integer threshold ) {
        this.modbusServerInfo = modbusServerInfo;
        this.modbusNodeInfoList = modbusNodeInfoList;
        this.stringRedisTemplate = stringRedisTemplate;
        this.threshold = threshold;
    }


    private void readModbusNodeValue(ModbusServerInfo modbusServerInfo, List<ModbusNodeInfo> modbusNodeInfoList){
        IpParameters ipParameters = new IpParameters();

        ipParameters.setHost(modbusServerInfo.getIp());
        ipParameters.setPort(Integer.parseInt(modbusServerInfo.getPort()));

        //创建modbus-tcp通信客户端连接
        ModbusMaster tcpMaster = ModbusFactoryProvide.getModbusFactory().createTcpMaster(ipParameters, true);

        try {
            tcpMaster.init();
            log.info("===========================     开始读取{} modbus设备节点值      ===========================",modbusServerInfo.getIp());

            for (ModbusNodeInfo modbusNodeInfo : modbusNodeInfoList) {
                Number number = ModbusProvide.readHoldingRegister(tcpMaster,modbusNodeInfo.getSlaveId() , modbusNodeInfo.getOffset(), DataType.TWO_BYTE_INT_UNSIGNED);
                String nodeId = modbusNodeInfo.getId();
                //统一缓存中的设备信号键
                stringRedisTemplate.opsForValue().set(DEVICE_SIGNAL+nodeId,number.intValue()>threshold?"1":"0");
                log.info("===========================  modbus {} 节点值：{}       ===========================",modbusNodeInfo.getNodeName(),number);
            }

        }  catch (ModbusInitException e) {
            log.error("Modbus TCP连接建立失败: {}", e.getMessage());
            throw new RuntimeException("Modbus连接失败，检查设备或网络配置", e);
        } catch (ModbusTransportException e) {
            log.error("Modbus Transport Error: {}", e.getMessage());
            throw new RuntimeException("Modbus传输错误，请检查请求和网络", e);
        } catch (ErrorResponseException e) {
            log.error("Modbus从机返回错误响应: {}", e.getErrorResponse());
            throw new RuntimeException("Modbus响应错误，请检查从机配置", e);
        }catch (Exception e){
            log.error("Modbus读取错误: {}", e.getMessage());
            e.printStackTrace();
        }finally {
            // 释放资源
            tcpMaster.destroy();
            log.info("Modbus连接已关闭");
        }
    }

    @Override
    public void run() {
        readModbusNodeValue(modbusServerInfo,modbusNodeInfoList);
    }

}
